// *************************************************************************************************
//
// MK3D Engine
// --------------------------------------
// Copyright (C) 2007-2011 Zeb (mailto: zebbey@gmail.com)
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// *************************************************************************************************

#ifndef __H_MK_TRANSFORMATION__
#define __H_MK_TRANSFORMATION__

namespace MK3DE
{
	//! Axis define
	enum AXIS_TYPE
	{
		AXIS_NONE = 0,
		AXIS_X = 1,
		AXIS_Y = 2,
		AXIS_Z = 3,
		AXIS_XY = 4,
		AXIS_YZ = 5,
		AXIS_XZ = 6,
		AXIS_XYZ = 7,
	};

	/**
	Store a node's relative translation, rotation, scale.
	When node update its transformation, call GetAbsoluteTransformation() to get a matrix, and
	multiply parent node's transformation.
	For example:
	class ChildNode : public Transformation
	{
		......

		void Update()
		{
			......

			BOOL dirty = FALSE;
			if (parentNode)
			dirty = UpdateTransformation(&parentNode->GetAbsoluteTransformation());
			else
			dirty = UpdateTransformation(NULL);                        

			......
		}

		......
	}
	*/
	class MK3DE_API CTransformation
	{
	public:
		CTransformation();
		virtual ~CTransformation();

		void SetRelativeTransformation(D3DXVECTOR3& translation, D3DXQUATERNION& rotation, D3DXVECTOR3& scale);

		void SetRelativeTranslation(D3DXVECTOR3& translation);
		void SetRelativeRotation(D3DXQUATERNION& rotation);
		void SetRelativeRotationYawPitchRoll(float yaw, float pitch, float roll);
		void SetRelativeScale(D3DXVECTOR3& scale);
		void SetRelativeScaleRotation(D3DXQUATERNION& sr);

		D3DXVECTOR3 GetRelativeTranslation()   { return _relativeTranslation;  }
		D3DXQUATERNION GetRelativeRotation()    { return _relativeRotation; }
		D3DXVECTOR3 GetRelativeScale()         { return _relativeScale; }

		BOOL UpdateAbsoluteTransformation(D3DXMATRIX* pMatParent);

		D3DXMATRIX& GetAbsoluteTransformation() { return _absoluteTransform; }
		D3DXMATRIX& GetRelativeTransformation() { return _relativeTransform; }

	private:
		void __UpdateTransformation();

	protected:
		BOOL _dirty;

		D3DXVECTOR3 _relativeTranslation;
		D3DXQUATERNION _relativeRotation;
		D3DXVECTOR3 _relativeScale;
		D3DXQUATERNION _relativeScaleRotation;

		D3DXMATRIX _relativeTransform;
		D3DXMATRIX _absoluteTransform;
	};
};

#endif /* __H_MK_TRANSFORMATION__ */